package cn.funeralobjects.ams.web.extension.config;

import cn.funeralobjects.ams.enums.RegionArea;
import cn.funeralobjects.ams.web.api.ProductApi;
import cn.funeralobjects.ams.web.api.ProductApiApi;
import cn.funeralobjects.ams.web.api.RegionApi;
import cn.funeralobjects.ams.web.model.*;
import cn.funeralobjects.common.model.KeyValue;
import com.aliyuncs.http.MethodType;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author FuneralObjects
 * Create date: 2020/5/28 6:50 PM
 */
@Configuration
@EnableConfigurationProperties(AmsProperties.class)
public class AmsRegisterAutoConfiguration {

    @Resource
    private AmsProperties amsProperties;

    @Resource
    private ProductApi productApi;

    @Resource
    private ProductApiApi productApiApi;

    @Resource
    private RegionApi regionApi;

    private static final Logger LOGGER = LoggerFactory.getLogger("AmsAutoRegister");


    @PostConstruct
    public void register() {
        if (!amsProperties.getRegister()) {
            return;
        }

        ConcurrentMap<MProduct, List<MProductApi>> productApisMap =
                amsProperties.getProducts().stream().map(product -> {
                    MProduct modify = new MProduct()
                            .setCode(product.getCode())
                            .setDescription(product.getDescription());
                    List<MProductApi> pApis = product.getApis().stream()
                            .map(pApi -> new MProductApi()
                                    .setAction(pApi.getAction())
//                                    .setCode(pApi.getCode())
                                    .setMethod(MethodType.valueOf(pApi.getMethod().toUpperCase()))
                                    .setVersion(pApi.getVersion()))
                            .collect(Collectors.toList());
                    return new KeyValue<>(modify, pApis);
                }).collect(Collectors.toConcurrentMap(KeyValue::getKey, KeyValue::getValue));

        List<VProduct> products = productApisMap.entrySet()
                .stream()
                .map(e -> {
                    MProduct modify = e.getKey();
                    AtomicReference<VProduct> entity = new AtomicReference<>(null);
                    productApi.findByCode(modify.getCode())
                            .switchIfEmpty(productApi.add(modify))
                            .subscribe(vProduct -> {
                                e.getValue().forEach(api -> api.setProductId(vProduct.getId()));
                                entity.set(vProduct);
                                ;
                            });
                    return entity.get();
                }).collect(Collectors.toList());

        Gson gson = new Gson();
        LOGGER.info("Products registered size: {}", products.size());
        if (LOGGER.isDebugEnabled()) {
            products.forEach(product -> LOGGER.debug("Product Registered:{}", gson.toJson(product)));
        }


        List<VProductApi> productApis = productApisMap.values()
                .stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toList())
                .stream()
                .map(mApi -> {
                    AtomicReference<VProductApi> entity = new AtomicReference<>(null);
                    productApiApi.findByActionAndVersionInProduct(mApi.getProductId(), mApi.getAction(), mApi.getVersion())
                            .switchIfEmpty(productApiApi.add(mApi))
                            .subscribe(entity::set);
                    return entity.get();
                }).collect(Collectors.toList());

        LOGGER.info("The Apis of Product registered size: {}", productApis.size());
        if (LOGGER.isDebugEnabled()) {
            productApis.forEach(api -> LOGGER.debug("Product Registered:{}", gson.toJson(api)));
        }


        List<VRegion> regions = amsProperties.getRegions()
                .stream()
                .map(region -> regionApi.findByRegionId(region.getRegionId())
                        .switchIfEmpty(regionApi.add(new MRegion().setRegionId(region.getRegionId()).setArea(RegionArea.valueOf(region.getArea())).setCityName(region.getCityName())))
                        .block()).collect(Collectors.toList());


        LOGGER.info("The Regions registered size: {}", regions.size());
        if (LOGGER.isDebugEnabled()) {
            regions.forEach(region -> LOGGER.debug("Product Registered:{}", gson.toJson(region)));
        }

    }


}
